﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;

/*
 一：构造方法(constructor)
又称为"构造器",就是在对象创建的时候，使用的方法
默认：一个类，在我们没有添加任何构造方法的时候，会由编辑器帮助我们生成一个无参数的构造方法
1：作用：当我们创建一个对象的时候，通过构造方法，可以完成对象的"初始化"
初始化：预先做一些初始的工作(字段赋值、属性赋值、读取配置信息、或者写入相关的其他设备信息...)
2：对象初始化的顺序：
首先、初始化字段和有显示赋值的属性，原因是如果字段没有初始化，属性或者私有字段在构造函数中，就无法调用。
其次、执行构造函数
四：构造方法承载
明白：一个类可以有若干构造方法，在构造对象的时候，我们可以选择自己需要的构造方法来完成对象初始化

【1】无参数构造方法在什么情况下使用？
通常我们给一下特定的和固定不变的成员(字段、属性或者配置文件读取等)
【2】有参数的构造方法？
根据需求，你希望用户创建对象的时候，做哪些初始化的工作，可以放到有参数的构造方法
不同：需要调用者从外面传递过来

构造方法相互调用
使用：this关键字(参数...)

无参数构造方法：只有在没有任何方法的情况下，编译器才会自动生成
所以，如果你设计一个类，需要用户在构建对象的时候，必须传递初始化的数据，就可以自己删掉无数的构造方法，
从而添加有参数的构造方法

构造方法重载的条件：
第一：不同构造方法的参数类型或个数必须不一样
构造方法重载的好处：
创建对象的时候，会综合到一起，提示给用户选择

5,this关键字
[1]在构造方法通用另一个构造方法的时候，可以使用
[2]this可以调用类的成员(字段、属性、方法)

this. 表示当前类(对象)

6.构造方法使用规范小结
public类名称(参数类型 参数名...)
{
//在这里可以初始化成员变量、属性、调用方法等都可以
//初始化控件...
}
要求：
【1】构造方法名称必须和类名一样
【2】不能有任何形式的返回值
【3】构造方法可以有参数，也可以没有参数
【4】构造方法可以重载

构造方法可以有强制性(如果我们删除无参数的构造方法时)

二、对象初始化器
类-->创建对象(new构造方法) (也叫做"对象实例化")
对象初始化器也是对象初始化的一种方法
特点：只能初始化属性！并且不需要做任何的额外的预制工作(代码)
使用：只需要在创建对象的时候，根据需求使用即可
总结：可以配合构造方法使用，而不是代替构造方法

三：实例方法
概念：通过对象(实例)去调用的方法，叫做实例方法，对象名.方法名
属性: 就是用来"保存"数据的
方法：就是为了得到我们需要的结果，使用属性或其他数据的过程(业务实现)
规范
访问修饰符 返回值类型 方法名称 （参数类型 参数名， 参数类型 参数名...)
{
//方法体

//return 返回结果
}
返回值类型：可以是我目前学过的所有数据类型，值类型，引用类型
如果没有返回值，使用void关键字
方法名：命名一定要使用Pascal命名法(首字母大写)

方法总结:
1.正确的确定访问修饰符(public/private)
封装的概念：首先就是我们不需要给别人使用的，我们都可以把它封装起来(private),需要给别人的必须用public去表露
            其次，封装也是把相关的业务逻辑组合到一起，任何根据不同的内容，划分不同的模块

2.命名规范：使用pasal命名法，其次要有意义，建议:动词+名称

3.方法返回值：类型根据需要确定，可以是基础数据类型，也可以是引用的对象类型

4.方法的参数：参数的个数，不宜过多，建议4-5个为上限

5.命名参数和参数默认值：要根据需要灵活使用


四：垃圾回收机制(GC)
概念：GC是.NET运行时内置的一个专门用来监听和销毁对象的组件
完全面向对象编程：在我们创建对象后，去使用，使用完毕后，GC会根据情况去清理

五：静态方法(static)
实例方法：通过"对象"去调用。对象名.方法名()
静态方法：通过"类名"去调用。类名.方法名()
特点：不需要构建对象，就可以使用
应用场合：程序的入口，或者需要在其他的类中，去共享这个变量或方法,我们可以适当的使用静态(static)修饰
一般使用特别频繁的场合或者需要多个类之间共享数据或者方法的时候，去使用
比如：通用的数据库访问类

静态的属性也是一样的

使用注意问题：
在静态方法里面不能直接调用"实例成员"(字段、方法、属性)
想使用，必须要通过实例

特别：实例方法内部，可以自己调用静态方法或字段、属性
总结：开发中，特别的实例成员用的最多。静态的慢慢去了解。因为静态的字段、属性，方法，不受GC控制，一直占用内存

params关键字
1.用途：当一个方法的参数不固定的时候，即存在可变参数的需求下，可以使用param
2.用法：可变的方法参数，也称为"数组型参数",也就是说必须定义数组类型
3.规范：
修饰符 返回类型 方法名(params 类型[] 变量名)
{
    //方法体内容
}
4.要求：
【1】该参数必须放到方法参数最后，并且只能用一次
【2】参数数组必须是一堆数组
【3】params不能与ref和out组合使用


*/

namespace CSharp_Object_Method
{
    /// <summary>
    /// 设备类
    /// </summary>
    public class Equipment
    {
        #region 构造方法
        public Equipment()
        {
            EquipId = 1000;
            //Pressures = 2.7; //只读无法初始化，因为没有私有字段
            SensorArray = new Sensor[5];
        }
        /// <summary>
        /// 构造方法
        /// </summary>
        /// <param name="equipId">设备编号</param>
        /// <param name="equipName">设备名称</param>
        public Equipment(int equipId, string equipName)
        {
            //_equipId = equipId;
            //EquipId = equipId;
            this.EquipId = equipId;
            EquipName = equipName;
        }
        public Equipment(int equipId, string equipName, string equipType) : this(equipId, equipName)
        {
            //EquipId = equipId;
            //EquipName = equipName;
            EquipType = equipType;
        }
        #endregion
        #region 属性
        private int _equipId = 0;
        public int EquipId
        {
            get { return _equipId; }
            set { _equipId = value; }
        }
        public string EquipName { get; set; } = string.Empty;
        public string EquipType { get; set; } = "KYJ.01";
        //业务类型的只读属性
        public double Pressures
        {
            get
            {
                double result = 2.5;
                return result;
            }
        }
        //private double pressure = 0.0;
        public double NewPressure { get; set; }

        public DateTime Collection => DateTime.Now;
        //对象数组类型的属性(基础类型的只读类型，有私有字段)
        public Sensor[] SensorArray { get; }
        private static int testData = 100;
        #endregion
        #region 实例方法
        //没有返回值，没有参数方法
        public void ShowInfo()
        {
            //在这里可以访问下位机...
            Console.WriteLine($"设备ID:{EquipId} 设备名称:{EquipName} 压力:{Pressures}");
        }
        /// <summary>
        /// 没有返回值，有参数的方法
        /// </summary>
        /// <param name="name"></param>
        /// <param name="pressure"></param>
        /// //没有返回值，有参数方法
        public void ShowInfo(string name,double pressure)
        {
            Console.WriteLine($"设备ID:{EquipId} 设备名称:{name} 压力:{pressure}");
        }
        //有返回值，没有参数方法
        public string GetEquipStatus()
        {
            return "正常";
        }
        //有返回值，没有参数方法
        public string GetEquipInfo(string name, double pressure)
        {
            string info = $"设备ID:{EquipId} 设备名称:{name} 压力:{pressure}";
            return info;
        }
        //返回一个对象的方法
        public Sensor GetSensor(int index)
        {
            return this.SensorArray[index];
        }
        //返回一个对象数组的方法
        /*public Sensor[] GetSensors(double temperature)
        {
        //以下代码会出错
            return this.SensorArray.Where(s=>s.Temperature > temperature).ToArray();
        }*/
        /// <summary>
        /// 默认值参数，必须放到最后
        /// </summary>
        /// <param name="equipId"></param>
        /// <param name="name"></param>
        /// <param name="temperature"></param>
        /// <returns></returns>
        public string GetEquipInfo(int equipId,string name, double temperature = 0.0)
        {
            double temp;
            if(temperature == 0.0)
            {
                temp = 0.0;
            }
            else
            {
                temp = temperature;
            }
            string info = $"设备ID:{EquipId} 设备名称:{name} 压力:{NewPressure}";
            return info;
        }
        #endregion
        #region 静态方法的使用
        public static string GetStaticInfo(string equipName)
        {
            Equipment equip = new Equipment(5001,"KLM005","KYJ-05");
            string result = $"设备ID:{equip.EquipId} 设备名称:{equipName} 压力:{equip.NewPressure} 测试数据：{testData}";
            return result;
        }
        #endregion
    }
}
